<?php
class MemberAreaPage extends Page {
	private static $db = array(
		'RestrictType' => "Enum(array('OnlyTheseGroups', 'OnlyTheseUsers', 'OnlyTheseNetworks', 'Any', 'None'), 'None')",
		'RestrictUsers' => 'MultiValueField',
		'RestrictNetwork' => 'MultiValueField'
	);
	
	private static $many_many = array(
		"RestrictGroups" => "Group"
	);

    private static $has_one = array();

    function populateDefaults() {
        $this->Title = FormField::name_to_label($this->class);
        $this->ShowInMenus = 1;
        $this->ShowInSearch = 0;
    }

    function requireDefaultRecords() {
        if(!$member_area_page = SiteTree::get_by_link('member-area')) {
            $member_area_page = new MemberAreaPage();
            $member_area_page->Title = 'Member Area';
            $member_area_page->URLSegment = 'member-area';
            $member_area_page->Status = 'Published';
            $member_area_page->ShowInMenus = 0;
            $member_area_page->Sort = 1;
            $member_area_page->write();
            $member_area_page->publish('Stage', 'Live');
            $member_area_page->flushCache();

            DB::alteration_message('Member Area page created', 'created');
        }

        $children = $member_area_page->allowedChildren();
        if(sizeof($children)) {
            foreach($children as $child) {
                if($child == 'MemberOverviewPage' || new $child instanceof MemberPage)
                    continue;
                if(!$page = DataObject::get_one($child)) {
                    $page = new $child;
                    $page->Status = 'Published';
                    $page->Sort = 1;
                    $page->ParentID = $member_area_page->ID;
                    $page->write();
                    $page->publish('Stage', 'Live');
                    $page->flushCache();

                    DB::alteration_message($page->Title . ' page created', 'created');
                }
            }
        }
    }

    public function allowedChildren() {
        $allowedChildren = array();
        if($this->class == 'MemberAreaPage') {
            $children = array_values(ClassInfo::subclassesFor('MemberOverviewPage'));
            array_push($children, 'Page');
            $children = array_unique($children);
            $exclude = array_values(ClassInfo::subclassesFor('MemberPage'));
            $exclude = array_unique($exclude);
            $allowed = array_diff($children, $exclude);
        }
        else if($this instanceof MemberOverviewPage && !$this instanceof MemberPage) {
            $allowed = array_values(ClassInfo::subclassesFor('MemberPage'));
            array_push($allowed, 'Page');
            $allowed = array_unique($allowed);
        }
        else{
            $allowed = parent::allowedChildren();
        }

        return $allowed;
    }
	
	/**
	 * Returns fields related to configuration aspects on this record, e.g. access control.
	 * See {@link getCMSFields()} for content-related fields.
	 * 
	 * @return FieldList
	 */
	public function getSettingsFields() {
		$fields = parent::getSettingsFields();
		
		$tab = $fields->findOrMakeTab('Root.Settings');
		
		$groupsMap = array();
		foreach(Group::get() as $group) {
			// Listboxfield values are escaped, use ASCII char instead of &raquo;
			$groupsMap[$group->ID] = $group->getBreadcrumbs(' > ');
		}
		asort($groupsMap);
		
		$restrictOptionsField = OptionsetField::create(
			"RestrictType", 
			_t('MemberAreaPage.RESTRICT_HEADER', "Who are restrict access this page?")
		);
		$restrictGroupsField = ListboxField::create("RestrictGroups", _t('MemberAreaPage.RESTRICT_GROUPS', "Restrict Groups"))
		->setMultiple(true)
		->setSource($groupsMap)
		->setAttribute(
			'data-placeholder', 
			_t('MemberAreaPage.GroupPlaceholder', 'Click to select group')
		);
		
		$restrictOptionsSource = array();
		$restrictOptionsSource['OnlyTheseGroups'] = _t('MemberAreaPage.ONLY_GROUPS', "Only these groups (choose from list)");
		$restrictOptionsSource['OnlyTheseUsers'] = _t('MemberAreaPage.ONLY_USERS', "Only these users");
		$restrictOptionsSource['OnlyTheseNetworks'] = _t('MemberAreaPage.ONLY_NETWORK', "Only user from these network");
		$restrictOptionsSource['Any'] = _t('MemberAreaPage.ANY', "Any from these below");
		$restrictOptionsSource['None'] = _t('MemberAreaPage.NONE', "None");
		$restrictOptionsField->setSource($restrictOptionsSource);
		
		$tab->Fields()->push($restrictOptionsField);
		$tab->Fields()->push($restrictGroupsField);
		$tab->Fields()->push($restrictUserField = MultiValueTextField::create('RestrictUsers', _t('MemberAreaPage.RESTRICT_USERS', "Restrict Users")));
		$tab->Fields()->push($restrictNetworkField = MultiValueTextField::create('RestrictNetwork', _t('MemberAreaPage.RESTRICT_NETWORK', "Restrict Network")));
		
		if(!Permission::check('SITETREE_GRANT_ACCESS')) {
			$fields->makeFieldReadonly($restrictGroupsField);
			$fields->makeFieldReadonly($restrictUserField);
			$fields->makeFieldReadonly($restrictNetworkField);
		}
		
		if($this->config()->runCMSFieldsExtensions) {
			$this->extend('updateSettingsFields', $fields);
		}
		
		return $fields;
	}
	
	/**
	 * This function should return true if the current user can view this
	 * page. It can be overloaded to customise the security model for an
	 * application.
	 * 
	 * Denies permission if any of the following conditions is TRUE:
	 * - canView() on any extension returns FALSE
	 * - "CanViewType" directive is set to "Inherit" and any parent page return false for canView()
	 * - "CanViewType" directive is set to "LoggedInUsers" and no user is logged in
	 * - "CanViewType" directive is set to "OnlyTheseUsers" and user is not in the given groups
	 *
	 * @uses DataExtension->canView()
	 * @uses ViewerGroups()
	 *
	 * @param Member|int|null $member
	 * @return boolean True if the current user can view this page.
	 */
	public function canView($member = null) {
		if(!$member || !(is_a($member, 'Member')) || is_numeric($member)) {
			$member = Distributor::currentUserID();
		}

		// admin override
		if(Permission::check(array("ADMIN", "SITETREE_VIEW_ALL"))) return true;

		// make sure we were loaded off an allowed stage

		// Were we definitely loaded directly off Live during our query?
		$fromLive = true;

		foreach (array('mode' => 'stage', 'stage' => 'live') as $param => $match) {
			$fromLive = $fromLive && strtolower((string)$this->getSourceQueryParam("Versioned.$param")) == $match;
		}

		if(!$fromLive
			&& !Session::get('unsecuredDraftSite')
			&& !Permission::check(array('CMS_ACCESS_LeftAndMain', 'CMS_ACCESS_CMSMain', 'VIEW_DRAFT_CONTENT'))) {
			// If we weren't definitely loaded from live, and we can't view non-live content, we need to
			// check to make sure this version is the live version and so can be viewed
			if (Versioned::get_versionnumber_by_stage($this->class, 'Live', $this->ID) != $this->Version) return false;
		}
		
		// Orphaned pages (in the current stage) are unavailable, except for admins via the CMS
		if($this->isOrphaned()) return false;

		// Standard mechanism for accepting permission changes from extensions
		if($member && is_numeric($member)) $member = DataObject::get_by_id('Member', $member);
		
		$extended = $this->extendedCan('canView', $member);
		if($extended !== null) return $extended;
		
		if(
			($this->RestrictType == 'OnlyTheseGroups' || $this->RestrictType == 'Any')
			&& $member 
			&& $member->inGroups($this->RestrictGroups())
		) return false;

		if(
			($this->RestrictType == 'OnlyTheseUsers' || $this->RestrictType == 'Any')
			&& $member 
			&& $this->dbObject('RestrictUsers')->Items()->find('Value', $member->Username)
		) {
			return false;
		}

		if(
			($this->RestrictType == 'OnlyTheseNetworks' || $this->RestrictType == 'Any')
			&& $member 
		) {
			foreach($this->dbObject('RestrictNetwork')->Items() as $item){
				$obj = Sponsor::get()->find('MemberID', Distributor::get_id_by_username($item->Title));
				if($obj && Sponsor::get()->filter('NLeft:GreaterThanOrEqual', (int)$obj->NLeft)->filter('NRight:LessThanOrEqual', (int)$obj->NRight)->filter('MemberID', $member->ID)->count()){
					return false;
				}
			}
		}

		if(Session::get('CustomLoginID') > 0 && !$member->canLoginView()){
			return false;
		}

		// check for inherit
		if($this->CanViewType == 'Inherit') {
			if($this->ParentID) return $this->Parent()->canView($member);
			else return $this->getSiteConfig()->canView($member);
		}
		
		// check for any logged-in users
		if($this->CanViewType == 'LoggedInUsers' && $member) {
			return true;
		}
		
		// check for specific groups
		if(
			$this->CanViewType == 'OnlyTheseUsers' 
			&& $member 
			&& $member->inGroups($this->ViewerGroups())
		) return true;

		return false;
	}

    function IsMemberArea(){
        return ($this instanceof MemberAreaPage);
    }
}

class MemberAreaPage_Controller extends Page_Controller {

    /**
     * An array of actions that can be accessed via a request. Each array element
     * should be an action name, and the
     * permissions or conditions required to allow the user to access it.
     *
     * <code>
     * array (
     *     'action', // anyone can access this action
     *     'action' => true, // same as above
     *     'action' => 'ADMIN', // you must have ADMIN permissions to access this
     * action
     *     'action' => '->checkAction' // you can only access this action if
     * $this->checkAction() returns true
     * );
     * </code>
     *
     * @var array
     */
    private static $allowed_actions = array(
        'Form'
    );

    public function init() {
        parent::init();
		$this->response->addHeader('X-Frame-Options', 'SAMEORIGIN');
        if($member = $this->CurrentMember()){
            if(!$member->AgreeTermAndCondition && !($this instanceof TermAndConditionPage_Controller) && !$this->redirectedTo() && !$member->canLogin()){
                return $this->redirect($this->TermAndConditionLink);
            }
            
            if($this->liveChildren()->count() && !$this->redirectedTo()) {
            	$defaultChild = null;
            	foreach($this->liveChildren() as $child){
            		if($child->canView()){
            			if(!$defaultChild){
            				$defaultChild = $child;
						}
						
						if($child->IsDefaultPage){
							$defaultChild = $child;
							break;
						}
            		}
            	}
                
				if($defaultChild){
                	return $this->redirect($defaultChild->Link());
				}
            }
    
            Config::inst()->update('i18n', 'date_format', $member->DateFormat);
            Config::inst()->update('i18n', 'time_format', $member->TimeFormat);
            HtmlEditorConfig::set_active('basic');
        }
    }
}
